package com.qf.realm;

import com.qf.pojo.SysUsers;
import com.qf.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.List;

public class MyUserRealm extends AuthorizingRealm {

    //注入service
    @Resource
    private UserService userService;

    /**
     * 每次调用该方法   需要查询权限和角色  浪费资源  性能差
     * 解决：整合缓存
     * 第一次访问后，存储到缓存中，之后直接从缓存中返回权限等信息，不需要再调用该方法
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        System.out.println("授权.........");

        //认证的时候  this.principals = new SimplePrincipalCollection(principal, realmName);
        //得到认证时候存储的用户信息
        SysUsers sysUser = (SysUsers) principals.getPrimaryPrincipal();
        int id = sysUser.getId();

        //Collection<String> permissions
        //查询这个用户具有的权限 根据id查询-->sys_user_role--->sys_role  -->sys_role_menu--> sys_menu(perms(权限))

        //用户具有的权限字符串
        List perms = userService.findPermByUid(id);
        //用户具有的角色
        List roles = userService.findRolesByUid(id);


        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //将数据库中查询到的权限字符串加入shiro框架
        authorizationInfo.addStringPermissions(perms);
        //将数据库中查询到的角色字符串加入shiro框架
        authorizationInfo.addRoles(roles);


        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //认证
        System.out.println("认证(登录比较用户名和密码)...........");

        //取出用户输入的用户名
        String username = (String)token.getPrincipal();

        //取出用户输入的密码, 注意密码  shiro处理成了  char[]
        String password = new String((char[])token.getCredentials());

        //根据用户输入的用户名, 到数据库中查询对应的用户对象
        SysUsers user = userService.findUserByName(username);

        //判断如果根据用户名没查出数据
        if (user == null){
            //没有这个用户名
            throw  new UnknownAccountException("账号不存在");
        }

        //对比用户输入的密码和数据库中该用户对应的密码是否一致
        if (!password.equals(user.getPassword())){
            throw new IncorrectCredentialsException("密码不对");
        }

        //判断用户状态status  1正常 0锁定
        if (user.getStatus() != 1){
            throw  new LockedAccountException("账号被锁定，请联系管理员");
        }

        //Object principal, Object credentials, String realmName
        /**
         * 参数一：把用户对象信息存储到shiro内部
         * 参数二：密码
         * 参数三：自定义realm名称
         */
        AuthenticationInfo info = new SimpleAuthenticationInfo(user, password, this.getName());

        return info;
    }
}